From a45afa4a5da04b31cb2f067bcecbb14cba1965a5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 20 Jun 2007 18:43:04 +0100 Subject: [PATCH] x86: Add hypercall function for retrieving EDD info. Signed-off-by: Jan Beulich Signed-off-by: Keir Fraser --- xen/arch/x86/boot/edd.S | 24 +++++------ xen/arch/x86/platform_hypercall.c | 72 +++++++++++++++++++++++++++++++ xen/arch/x86/setup.c | 2 +- xen/include/asm-x86/edd.h | 18 ++++++-- xen/include/public/platform.h | 32 ++++++++++++++ 5 files changed, 131 insertions(+), 17 deletions(-) diff --git a/xen/arch/x86/boot/edd.S b/xen/arch/x86/boot/edd.S index fcc8132e5e..51d20d0500 100644 --- a/xen/arch/x86/boot/edd.S +++ b/xen/arch/x86/boot/edd.S @@ -24,7 +24,7 @@ /* Maximum number of EDD information structures at boot_edd_info. */ #define EDD_INFO_MAX 6 -/* Maximum number of MBR signatures at boot_edd_signature. */ +/* Maximum number of MBR signatures at boot_mbr_signature. */ #define EDD_MBR_SIG_MAX 16 /* Size of components of EDD information structure. */ @@ -40,10 +40,8 @@ get_edd: # Read the first sector of each BIOS disk device and store the 4-byte signature edd_mbr_sig_start: movb $0x80, %dl # from device 80 - movw $bootsym(boot_edd_signature),%bx # store buffer ptr in bx + movw $bootsym(boot_mbr_signature),%bx # store buffer ptr in bx edd_mbr_sig_read: - movl $0xFFFFFFFF, %eax - movl %eax, (%bx) # assume failure pushw %bx movb $0x02, %ah # 0x02 Read Sectors movb $1, %al # read 1 sector @@ -64,11 +62,12 @@ edd_mbr_sig_read: cmpb $0, %ah # some BIOSes do not set CF jne edd_mbr_sig_done # on failure, we're done. movl bootsym(boot_edd_info)+EDD_MBR_SIG_OFFSET,%eax - movl %eax, (%bx) # store signature from MBR - incb bootsym(boot_edd_signature_nr) # note that we stored something + movb %dl, (%bx) # store BIOS drive number + movl %eax, 4(%bx) # store signature from MBR + incb bootsym(boot_mbr_signature_nr) # note that we stored something incb %dl # increment to next device - addw $4, %bx # increment sig buffer ptr - cmpb $EDD_MBR_SIG_MAX,bootsym(boot_edd_signature_nr) + addw $8, %bx # increment sig buffer ptr + cmpb $EDD_MBR_SIG_MAX,bootsym(boot_mbr_signature_nr) jb edd_mbr_sig_read edd_mbr_sig_done: @@ -150,12 +149,13 @@ edd_done: opt_edd: .byte 0 # edd=on/off/skipmbr -.globl boot_edd_info_nr, boot_edd_signature_nr +.globl boot_edd_info, boot_edd_info_nr +.globl boot_mbr_signature, boot_mbr_signature_nr boot_edd_info_nr: .byte 0 -boot_edd_signature_nr: +boot_mbr_signature_nr: .byte 0 -boot_edd_signature: - .fill EDD_MBR_SIG_MAX*4,1,0 +boot_mbr_signature: + .fill EDD_MBR_SIG_MAX*8,1,0 boot_edd_info: .fill 512,1,0 # big enough for a disc sector diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index 766a357e65..5478bc34be 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -20,12 +20,17 @@ #include #include #include +#include #include #include "cpu/mtrr/mtrr.h" #ifndef COMPAT typedef long ret_t; DEFINE_SPINLOCK(xenpf_lock); +# undef copy_from_compat +# define copy_from_compat copy_from_guest +# undef copy_to_compat +# define copy_to_compat copy_to_guest #else extern spinlock_t xenpf_lock; #endif @@ -151,6 +156,73 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) } break; + case XENPF_firmware_info: + switch ( op->u.firmware_info.type ) + { + case XEN_FW_DISK_INFO: { + const struct edd_info *info; + u16 length; + + ret = -ESRCH; + if ( op->u.firmware_info.index >= bootsym(boot_edd_info_nr) ) + break; + + info = bootsym(boot_edd_info) + op->u.firmware_info.index; + + /* Transfer the EDD info block. */ + ret = -EFAULT; + if ( copy_from_compat(&length, op->u.firmware_info.u. + disk_info.edd_params, 1) ) + break; + if ( length > info->edd_device_params.length ) + length = info->edd_device_params.length; + if ( copy_to_compat(op->u.firmware_info.u.disk_info.edd_params, + (u8 *)&info->edd_device_params, + length) ) + break; + if ( copy_to_compat(op->u.firmware_info.u.disk_info.edd_params, + &length, 1) ) + break; + + /* Transfer miscellaneous other information values. */ +#define C(x) op->u.firmware_info.u.disk_info.x = info->x; + C(device); + C(version); + C(interface_support); + C(legacy_max_cylinder); + C(legacy_max_head); + C(legacy_sectors_per_track); +#undef C + + ret = (copy_field_to_guest(u_xenpf_op, op, + u.firmware_info.u.disk_info) + ? -EFAULT : 0); + break; + } + case XEN_FW_DISK_MBR_SIGNATURE: { + const struct mbr_signature *sig; + + ret = -ESRCH; + if ( op->u.firmware_info.index >= bootsym(boot_mbr_signature_nr) ) + break; + + sig = bootsym(boot_mbr_signature) + op->u.firmware_info.index; + + op->u.firmware_info.u.disk_mbr_signature.device = sig->device; + op->u.firmware_info.u.disk_mbr_signature.mbr_signature = + sig->signature; + + ret = (copy_field_to_guest(u_xenpf_op, op, + u.firmware_info.u.disk_mbr_signature) + ? -EFAULT : 0); + break; + } + default: + ret = -EINVAL; + break; + } + break; + default: ret = -ENOSYS; break; diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index c630cb242f..12dad990b0 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -505,7 +505,7 @@ void __init __start_xen(unsigned long mbi_p) printk("Disc information:\n"); printk(" Found %d MBR signatures\n", - bootsym(boot_edd_signature_nr)); + bootsym(boot_mbr_signature_nr)); printk(" Found %d EDD information structures\n", bootsym(boot_edd_info_nr)); diff --git a/xen/include/asm-x86/edd.h b/xen/include/asm-x86/edd.h index 4079dafe09..bfab9d3930 100644 --- a/xen/include/asm-x86/edd.h +++ b/xen/include/asm-x86/edd.h @@ -32,12 +32,22 @@ struct edd_info { u16 legacy_max_cylinder; /* %cl[7:6]:%ch: maximum cylinder number */ u8 legacy_max_head; /* %dh: maximum head number */ u8 legacy_sectors_per_track; /* %cl[5:0]: maximum sector number */ - /* Int13, Fn41: Get Device Parameters */ - u8 edd_device_params[74]; /* as filled into %ds:%si */ + /* Int13, Fn41: Get Device Parameters (as filled into %ds:%esi). */ + struct { + u16 length; + u8 data[72]; + } edd_device_params; } __attribute__ ((packed)); -extern u32 boot_edd_signature[]; -extern u8 boot_edd_signature_nr; +struct mbr_signature { + u8 device; + u8 pad[3]; + u32 signature; +} __attribute__ ((packed)); + +/* These all reside in the boot trampoline. Access via bootsym(). */ +extern struct mbr_signature boot_mbr_signature[]; +extern u8 boot_mbr_signature_nr; extern struct edd_info boot_edd_info[]; extern u8 boot_edd_info_nr; diff --git a/xen/include/public/platform.h b/xen/include/public/platform.h index 2937b4d31d..50e3b5149c 100644 --- a/xen/include/public/platform.h +++ b/xen/include/public/platform.h @@ -114,6 +114,37 @@ struct xenpf_platform_quirk { typedef struct xenpf_platform_quirk xenpf_platform_quirk_t; DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t); +#define XENPF_firmware_info 50 +#define XEN_FW_DISK_INFO 1 +#define XEN_FW_DISK_MBR_SIGNATURE 2 +struct xenpf_firmware_info { + /* IN variables. */ + uint32_t type; + uint32_t index; + /* OUT variables. */ + union { + struct { + /* Int13, Fn48: Check Extensions Present. */ + uint8_t device; /* %dl: bios device number */ + uint8_t version; /* %ah: major version */ + uint16_t interface_support; /* %cx: support bitmap */ + /* Int13, Fn08: Legacy Get Device Parameters. */ + uint16_t legacy_max_cylinder; /* %cl[7:6]:%ch: max cyl # */ + uint8_t legacy_max_head; /* %dh: max head # */ + uint8_t legacy_sectors_per_track; /* %cl[5:0]: max sector # */ + /* Int13, Fn41: Get Device Parameters (as filled into %ds:%esi). */ + /* NB. First uint16_t of buffer must be set to buffer size. */ + XEN_GUEST_HANDLE(void) edd_params; + } disk_info; /* XEN_FW_DISK_INFO */ + struct { + uint8_t device; /* bios device number */ + uint32_t mbr_signature; /* offset 0x1b8 in mbr */ + } disk_mbr_signature; /* XEN_FW_DISK_MBR_SIGNATURE */ + } u; +}; +typedef struct xenpf_firmware_info xenpf_firmware_info_t; +DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t); + struct xen_platform_op { uint32_t cmd; uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ @@ -124,6 +155,7 @@ struct xen_platform_op { struct xenpf_read_memtype read_memtype; struct xenpf_microcode_update microcode; struct xenpf_platform_quirk platform_quirk; + struct xenpf_firmware_info firmware_info; uint8_t pad[128]; } u; }; -- 2.30.2